cmake_minimum_required(VERSION 3.4.3)
project(hip)
# sample command for hip-vdi, you'll need to have vdi installed
#  cmake -DHIP_COMPILER=clang -DHIP_PLATFORM=vdi ..
#  cmake -DHIP_COMPILER=clang -DHIP_PLATFORM=vdi -DVDI_DIR=/extra/lmoriche/hip-vdi/vdi -DOPENCL_DIR=/extra/lmoriche/clients/lmoriche_opencl_dev2/drivers/opencl/api/opencl -DLIBVDI_STATIC_DIR=/extra/lmoriche/hip-vdi/build/vdi ..

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

#############################
# Options
#############################
option(BUILD_HIPIFY_CLANG "Enable building the CUDA->HIP converter" OFF)

#############################
# Setup config generation
#############################
string(TIMESTAMP _timestamp UTC)
set(_versionInfo "# Auto-generated by cmake\n")
set(_buildInfo "# Auto-generated by cmake on ${_timestamp} UTC\n")
macro(add_to_config _configfile _variable)
    set(${_configfile} "${${_configfile}}${_variable}=${${_variable}}\n")
endmacro()

#############################
# Setup version information
#############################
# Determine HIP_BASE_VERSION
set(ENV{HIP_PATH} "")
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bin/hipconfig --version
    OUTPUT_VARIABLE HIP_BASE_VERSION
    OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "." ";" VERSION_LIST ${HIP_BASE_VERSION})
list(GET VERSION_LIST 0 HIP_VERSION_MAJOR)
list(GET VERSION_LIST 1 HIP_VERSION_MINOR)

# get date information based on UTC
# use the last two digits of year + week number + day in the week as HIP_VERSION_GITDATE
# use the commit date, instead of build date
# add xargs to remove strange trailing newline character
execute_process(COMMAND git show -s --format=@%ct
    COMMAND xargs
    COMMAND date -f - --utc +%y%U%w
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    OUTPUT_VARIABLE HIP_VERSION_GITDATE
    OUTPUT_STRIP_TRAILING_WHITESPACE)

# get commit short hash
execute_process(COMMAND git rev-parse --short HEAD
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    OUTPUT_VARIABLE HIP_VERSION_GITHASH
    OUTPUT_STRIP_TRAILING_WHITESPACE)

# get commit count
execute_process(COMMAND git rev-list --count HEAD
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    OUTPUT_VARIABLE HIP_VERSION_GITCOUNT
    OUTPUT_STRIP_TRAILING_WHITESPACE)

set(HIP_VERSION_PATCH ${HIP_VERSION_GITDATE}-${HIP_VERSION_GITHASH})
add_to_config(_versionInfo HIP_VERSION_MAJOR)
add_to_config(_versionInfo HIP_VERSION_MINOR)
add_to_config(_versionInfo HIP_VERSION_PATCH)

if(CMAKE_CXX_COMPILER MATCHES ".*hcc")
    set(HIP_COMPILER "hcc" CACHE STRING "HIP Compiler")
    set(HIP_PLATFORM "hcc" CACHE STRING "HIP Platform")
    get_filename_component(CXX_PATH ${CMAKE_CXX_COMPILER} DIRECTORY)
    get_filename_component(CXX_PATH ${CXX_PATH} DIRECTORY)
    set(HCC_HOME "${CXX_PATH}" CACHE PATH "Path to which HCC has been installed")
endif()

# overwrite HIP_VERSION_PATCH for packaging
if(DEFINED ENV{ROCM_BUILD_ID})
    set(HIP_VERSION_PATCH ${HIP_VERSION_GITDATE}.${HIP_VERSION_GITCOUNT}-$ENV{ROCM_BUILD_ID}-${HIP_VERSION_GITHASH})
else()
    set(HIP_VERSION_PATCH ${HIP_VERSION_GITDATE}.${HIP_VERSION_GITCOUNT}-${HIP_VERSION_GITHASH})
endif()
set(HIP_VERSION ${HIP_VERSION_MAJOR}.${HIP_VERSION_MINOR}.${HIP_VERSION_PATCH})

#############################
# Configure variables
#############################
# Determine HIP_PLATFORM
if(NOT DEFINED HIP_PLATFORM)
    if(NOT DEFINED ENV{HIP_PLATFORM})
        execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bin/hipconfig --platform
            OUTPUT_VARIABLE HIP_PLATFORM
            OUTPUT_STRIP_TRAILING_WHITESPACE)
    else()
        set(HIP_PLATFORM $ENV{HIP_PLATFORM} CACHE STRING "HIP Platform")
    endif()
endif()
message(STATUS "HIP Platform: " ${HIP_PLATFORM})

# Determine HIP_COMPILER
# Either hcc or clang; default is hcc
if(NOT DEFINED HIP_COMPILER)
    if(NOT DEFINED ENV{HIP_COMPILER})
        set(HIP_COMPILER "hcc" CACHE STRING "HIP Compiler")
    else()
        set(HIP_COMPILER $ENV{HIP_COMPILER} CACHE STRING "HIP Compiler")
    endif()
endif()
if(NOT (HIP_COMPILER STREQUAL "hcc" OR HIP_COMPILER STREQUAL "clang"))
    message(FATAL_ERROR "Must use HIP_COMPILER as hcc or clang")
endif()
message(STATUS "HIP Compiler: " ${HIP_COMPILER})
add_to_config(_buildInfo HIP_COMPILER)

# Determine HIP_RUNTIME
# Either HCC or VDI; default is HCC
if(NOT DEFINED ENV{HIP_RUNTIME})
  if(HIP_PLATFORM STREQUAL "hcc")
    set(HIP_RUNTIME "HCC" CACHE STRING "HIP Runtime")
  elseif (HIP_PLATFORM STREQUAL "vdi")
    set(HIP_RUNTIME "VDI" CACHE STRING "HIP Runtime")
  elseif (HIP_PLATFORM STREQUAL "nvcc")
    set(HIP_RUNTIME "CUDA" CACHE STRING "HIP Runtime")
  endif()
endif()
add_to_config(_buildInfo HIP_RUNTIME)

if(HIP_PLATFORM STREQUAL "vdi")
   set(USE_PROF_API "1")
endif()

# If HIP_PLATFORM is hcc, we need HCC_HOME and HSA_PATH to be defined
if(HIP_PLATFORM STREQUAL "hcc")
    # Determine HCC_HOME
    if(NOT DEFINED HCC_HOME)
        if(NOT DEFINED ENV{HCC_HOME})
            set(HCC_HOME "/opt/rocm/hcc" CACHE PATH "Path to which HCC has been installed")
        else()
            set(HCC_HOME $ENV{HCC_HOME} CACHE PATH "Path to which HCC has been installed")
        endif()
    endif()

    if(DEFINED ENV{HIP_DEVELOPER})
        add_to_config(_buildInfo HCC_HOME)
    endif()
    if(IS_ABSOLUTE ${HCC_HOME} AND EXISTS ${HCC_HOME} AND IS_DIRECTORY ${HCC_HOME})
        execute_process(COMMAND ${HCC_HOME}/bin/hcc --version
            OUTPUT_VARIABLE HCC_VERSION
            OUTPUT_STRIP_TRAILING_WHITESPACE)
        string(REGEX REPLACE ".*based on HCC " "" HCC_VERSION ${HCC_VERSION})
        string(REGEX REPLACE " .*" "" HCC_VERSION ${HCC_VERSION})
        message(STATUS "Looking for HCC in: " ${HCC_HOME} ". Found version: " ${HCC_VERSION})
    else()
        message(FATAL_ERROR "Don't know where to find HCC. Please specify abolute path using -DHCC_HOME")
    endif()
    add_to_config(_buildInfo HCC_VERSION)
    string(REPLACE "-" ";" HCC_VERSION_LIST ${HCC_VERSION})
    list(GET HCC_VERSION_LIST 0 HCC_PACKAGE_VERSION)
    string(REPLACE "." ";" HCC_VERSION_LIST ${HCC_PACKAGE_VERSION})
    list(GET HCC_VERSION_LIST 0 HCC_VERSION_MAJOR)
    list(GET HCC_VERSION_LIST 1 HCC_VERSION_MINOR)

    # Determine HSA_PATH
    if(NOT DEFINED HSA_PATH)
        if(NOT DEFINED ENV{HSA_PATH})
            set(HSA_PATH "/opt/rocm/hsa" CACHE PATH "Path to which HSA runtime has been installed")
        else()
            set(HSA_PATH $ENV{HSA_PATH} CACHE PATH "Path to which HSA runtime has been installed")
        endif()
    endif()
    if(IS_ABSOLUTE ${HSA_PATH} AND EXISTS ${HSA_PATH} AND IS_DIRECTORY ${HSA_PATH})
        message(STATUS "Looking for HSA runtime in: " ${HSA_PATH})
    else()
        message(FATAL_ERROR "Don't know where to find HSA runtime. Please specify absolute path using -DHSA_PATH")
    endif()
endif()

# Set default build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()

# Determine HIP install path
if (UNIX)
    set(HIP_DEFAULT_INSTALL_PREFIX "/opt/rocm/hip")
endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
    if(CMAKE_BUILD_TYPE MATCHES Debug)
        set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Installation path for HIP" FORCE)
    elseif(CMAKE_BUILD_TYPE MATCHES Release)
        set(CMAKE_INSTALL_PREFIX ${HIP_DEFAULT_INSTALL_PREFIX} CACHE PATH "Installation path for HIP" FORCE)
    else()
        message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE specified. Valid values are Debug and Release")
    endif()
endif()

# Set default install path as "/opt/rocm/hip", can override the path from cmake build.
set(CPACK_INSTALL_PREFIX ${HIP_DEFAULT_INSTALL_PREFIX} CACHE PATH "Package Installation path for HIP")

if(IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})
    message(STATUS "HIP will be installed in: " ${CMAKE_INSTALL_PREFIX})
else()
    message(FATAL_ERROR "Don't know where to install HIP. Please specify absolute path using -DCMAKE_INSTALL_PREFIX")
endif()

if (NOT DEFINED ROCM_PATH )
     set ( ROCM_PATH "/opt/rocm"  CACHE STRING "Default ROCM installation directory." )
endif ()
message (STATUS "ROCM Installation path(ROCM_PATH): ${ROCM_PATH}")

# set the installation path for the installer package
set(CPACK_SET_DESTDIR ON CACHE BOOL "Installer package will install hip to CMAKE_INSTALL_PREFIX instead of CPACK_PACKAGING_INSTALL_PREFIX")
if (NOT CPACK_SET_DESTDIR)
  set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/rocm/hip" CACHE PATH "Default installation path of hcc installer package")
endif (NOT CPACK_SET_DESTDIR)

#############################
# Profiling API support
#############################
# Generate profiling API macros/structures header
if(HIP_PLATFORM STREQUAL "hcc")
if(USE_PROF_API EQUAL 1)
set(PROF_API_STR "${CMAKE_CURRENT_SOURCE_DIR}/include/hip/hcc_detail/hip_prof_str.h")
set(PROF_API_HDR "${CMAKE_CURRENT_SOURCE_DIR}/include/hip/hcc_detail/hip_runtime_api.h")
set(PROF_API_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(PROF_API_GEN "${CMAKE_CURRENT_SOURCE_DIR}/hip_prof_gen.py")
set(PROF_API_LOG "${PROJECT_BINARY_DIR}/hip_prof_gen.log.txt")
set(PROF_API_CMD "${PROF_API_GEN} -v ${OPT_PROF_API} ${PROF_API_HDR} ${PROF_API_SRC} ${PROF_API_STR} >${PROF_API_LOG}")
MESSAGE(STATUS "Generating profiling promitives: ${PROF_API_STR}")
execute_process(COMMAND sh -c "rm -f ${PROF_API_STR}; ${PROF_API_CMD}")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PROF_API_GEN} ${PROF_API_HDR} ${PROF_API_STR})

# Enable profiling API
    find_path(PROF_API_HEADER_DIR prof_protocol.h
        HINTS
            ${PROF_API_HEADER_PATH}
        PATHS
            /opt/rocm/roctracer
        PATH_SUFFIXES
            include/ext
    )
    if(NOT PROF_API_HEADER_DIR)
        MESSAGE(WARNING "Profiling API header not found. Disabling roctracer integration. Use -DPROF_API_HEADER_PATH=<path to prof_protocol.h header>")
    else()
        add_definitions(-DUSE_PROF_API=1)
        include_directories(${PROF_API_HEADER_DIR})
        MESSAGE(STATUS "Profiling API: ${PROF_API_HEADER_DIR}")
    endif()
endif()
endif()

#############################
# Build steps
#############################
set(BIN_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin)
set(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib)
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include)
set(CONFIG_PACKAGE_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/hip)

# Build clang hipify if enabled
if (BUILD_HIPIFY_CLANG)
    add_subdirectory(hipify-clang)
endif()

# Build LPL an CA (fat binary generation / fat binary decomposition tools) if
# platform is hcc; do this before the ugly hijacking of the compiler, since no
# HC code is involved.
#if (HIP_PLATFORM STREQUAL "hcc")
#    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lpl_ca)
#endif ()

if(HIP_PLATFORM STREQUAL "vdi")
    # Determine HSA_PATH
    if(NOT DEFINED HSA_PATH)
        if(NOT DEFINED ENV{HSA_PATH})
            set(HSA_PATH "/opt/rocm/hsa" CACHE PATH "Path to which HSA runtime has been installed")
        else()
            set(HSA_PATH $ENV{HSA_PATH} CACHE PATH "Path to which HSA runtime has been installed")
        endif()
    endif()
    if(IS_ABSOLUTE ${HSA_PATH} AND EXISTS ${HSA_PATH} AND IS_DIRECTORY ${HSA_PATH})
        message(STATUS "Looking for HSA runtime in: " ${HSA_PATH})
    else()
        message(FATAL_ERROR "Don't know where to find HSA runtime. Please specify absolute path using -DHSA_PATH")
    endif()

    include_directories(${PROJECT_SOURCE_DIR}/include)
    add_subdirectory(vdi)
    file(WRITE "${PROJECT_BINARY_DIR}/.hipInfo" ${_buildInfo})


# set(VDI_CXX_FLAGS  "-hc -fno-gpu-rdc --amdgpu-target=gfx803 --amdgpu-target=gfx900 --amdgpu-target=gfx906 --amdgpu-target=gfx908 ")
    set(HIP_VDI_BUILD_FLAGS "${HIP_VDI_BUILD_FLAGS} -fPIC ${VDI_CXX_FLAGS} -I${HSA_PATH}/include")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${HIP_VDI_BUILD_FLAGS}")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HIP_VDI_BUILD_FLAGS}")
    set(HCC_CXX_FLAGS  "-hc -fno-gpu-rdc --amdgpu-target=gfx803 --amdgpu-target=gfx900 --amdgpu-target=gfx906 --amdgpu-target=gfx908 ")
    set(HIP_HCC_BUILD_FLAGS "${HIP_HCC_BUILD_FLAGS} -fPIC ${HCC_CXX_FLAGS} -I${HSA_PATH}/include")

endif()

message(STATUS "\nHSA runtime in: " ${HSA_PATH})
# Build hip_hcc if platform is hcc
if(HIP_PLATFORM STREQUAL "hcc")
    include_directories(${PROJECT_SOURCE_DIR}/include)
    set(HIP_HCC_BUILD_FLAGS)

    # Add HIP_VERSION to CMAKE_<LANG>_FLAGS
    set(HIP_HCC_BUILD_FLAGS "${HIP_HCC_BUILD_FLAGS} -DHIP_VERSION_MAJOR=${HIP_VERSION_MAJOR} -DHIP_VERSION_MINOR=${HIP_VERSION_MINOR} -DHIP_VERSION_PATCH=${HIP_VERSION_GITDATE}")

    # Add remaining flags
    set(HCC_CXX_FLAGS  "-Xlinker --enable-new-dtags -hc -fno-gpu-rdc --amdgpu-target=gfx803 --amdgpu-target=gfx900 --amdgpu-target=gfx906 --amdgpu-target=gfx908 ")
    set(HIP_HCC_BUILD_FLAGS "${HIP_HCC_BUILD_FLAGS} -fPIC ${HCC_CXX_FLAGS} -I${HSA_PATH}/include")

    # Set compiler and compiler flags
    set(CMAKE_CXX_COMPILER "${HCC_HOME}/bin/hcc")
    set(CMAKE_C_COMPILER   "${HCC_HOME}/bin/hcc")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HIP_HCC_BUILD_FLAGS}")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${HIP_HCC_BUILD_FLAGS}")

    set(SOURCE_FILES_RUNTIME
        src/program_state.cpp
        src/hip_clang.cpp
        src/hip_hcc.cpp
        src/hip_context.cpp
        src/hip_device.cpp
        src/hip_error.cpp
        src/hip_event.cpp
        src/hip_fatbin.cpp
        src/hip_memory.cpp
        src/hip_peer.cpp
        src/hip_stream.cpp
        src/hip_module.cpp
        src/hip_db.cpp
        src/grid_launch.cpp
        src/hip_texture.cpp
        src/hip_surface.cpp
        src/hip_intercept.cpp
        src/env.cpp
        src/h2f.cpp)

    set ( HIP_LIB_VERSION_MAJOR ${HIP_VERSION_MAJOR} )
    set ( HIP_LIB_VERSION_MINOR ${HIP_VERSION_MINOR} )
    if ( ${ROCM_PATCH_VERSION} )
        set ( HIP_LIB_VERSION_PATCH ${ROCM_PATCH_VERSION})
    else ()
        set ( HIP_LIB_VERSION_PATCH ${HIP_VERSION_PATCH} )
    endif ()
    set ( HIP_LIB_VERSION_STRING "${HIP_LIB_VERSION_MAJOR}.${HIP_LIB_VERSION_MINOR}.${HIP_LIB_VERSION_PATCH}" )

    if ( DEFINED ENV{ROCM_RPATH} )
        set (CMAKE_INSTALL_RPATH "$ENV{ROCM_RPATH}" )
        set (CMAKE_BUILD_WITH_INSTALL_RPATH TRUE )
        set (CMAKE_SKIP_BUILD_RPATH TRUE )
    endif ()
    add_library(hip_hcc SHARED ${SOURCE_FILES_RUNTIME})
    add_library(hip_hcc_static STATIC ${SOURCE_FILES_RUNTIME})

    ## Set the VERSION and SOVERSION values
    set_property ( TARGET hip_hcc PROPERTY VERSION "${HIP_LIB_VERSION_STRING}" )
    set_property ( TARGET hip_hcc PROPERTY SOVERSION "${HIP_LIB_VERSION_MAJOR}" )

    target_link_libraries(hip_hcc PRIVATE hc_am)
    target_link_libraries(hip_hcc_static PRIVATE hc_am)

    add_library(hiprtc SHARED src/hiprtc.cpp)
    target_compile_options(hiprtc PRIVATE -DDISABLE_REDUCED_GPU_BLOB_COPY)
    set_property ( TARGET hiprtc PROPERTY VERSION "${HIP_LIB_VERSION_STRING}" )
    set_property ( TARGET hiprtc PROPERTY SOVERSION "${HIP_LIB_VERSION_MAJOR}" )

    target_include_directories(
        hiprtc SYSTEM
            PRIVATE ${PROJECT_SOURCE_DIR}/include ${HSA_PATH}/include)

    set_target_properties(hip_hcc PROPERTIES CXX_VISIBILITY_PRESET hidden)
    set_target_properties(hip_hcc PROPERTIES VISIBILITY_INLINES_HIDDEN 1)
    set_target_properties(hiprtc PROPERTIES CXX_VISIBILITY_PRESET hidden)
    set_target_properties(hiprtc PROPERTIES VISIBILITY_INLINES_HIDDEN 1)


    if(HIP_PLATFORM STREQUAL "hcc")
        find_package(amd_comgr REQUIRED CONFIG
            PATHS
                /opt/rocm/
            PATH_SUFFIXES
                cmake/amd_comgr
                lib/cmake/amd_comgr
        )
        MESSAGE(STATUS "Code Object Manager found at ${amd_comgr_DIR}.")
    endif()

    target_link_libraries(hip_hcc PRIVATE amd_comgr)
    target_link_libraries(hip_hcc_static PRIVATE amd_comgr)

    string(REPLACE " " ";" HCC_CXX_FLAGS_LIST ${HCC_CXX_FLAGS})
    foreach(TARGET hip_hcc hip_hcc_static)
        target_include_directories(${TARGET} SYSTEM INTERFACE $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>;${HSA_PATH}/include)
    endforeach()
    add_library(host INTERFACE)
    target_link_libraries(host INTERFACE hip_hcc)
    add_library(device INTERFACE)
    if(HIP_COMPILER STREQUAL "hcc")
        target_link_libraries(device INTERFACE host hcc::hccrt hcc::hc_am)
    else()
        target_link_libraries(device INTERFACE host)
    endif()

    # Generate .hipInfo
    file(WRITE "${PROJECT_BINARY_DIR}/.hipInfo" ${_buildInfo})
endif()

if(HIP_PLATFORM STREQUAL "hcc" OR HIP_PLATFORM STREQUAL "vdi")
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lpl_ca)
endif()
# Generate .hipVersion
file(WRITE "${PROJECT_BINARY_DIR}/.hipVersion" ${_versionInfo})

# Generate hip_version.h
set(_versionInfoHeader
"// Auto-generated by cmake\n
#ifndef HIP_VERSION_H
#define HIP_VERSION_H\n
#define HIP_VERSION_MAJOR ${HIP_VERSION_MAJOR}
#define HIP_VERSION_MINOR ${HIP_VERSION_MINOR}
#define HIP_VERSION_PATCH ${HIP_VERSION_GITDATE}
#define HIP_VERSION       (HIP_VERSION_MAJOR * 100 + HIP_VERSION_MINOR)\n
#endif\n
")
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/include/hip/hip_version.h" ${_versionInfoHeader})

# Build doxygen documentation
find_program(DOXYGEN_EXE doxygen)
if(DOXYGEN_EXE)
    add_custom_target(doc COMMAND HIP_PATH=${CMAKE_CURRENT_SOURCE_DIR} ${DOXYGEN_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/docs/doxygen-input/doxy.cfg
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/docs)
endif()

#############################
# Install steps
#############################
# Install hip_hcc if platform is hcc
if(HIP_PLATFORM STREQUAL "hcc")
    install(TARGETS hip_hcc_static hip_hcc hiprtc DESTINATION lib)
endif()

# Install .hipInfo
if(HIP_PLATFORM STREQUAL "hcc" OR HIP_PLATFORM STREQUAL "vdi")
    install(FILES ${PROJECT_BINARY_DIR}/.hipInfo DESTINATION lib)
endif()

# Install .hipVersion
install(FILES ${PROJECT_BINARY_DIR}/.hipVersion DESTINATION bin)

# Install src, bin, include & cmake if necessary
execute_process(COMMAND test ${CMAKE_INSTALL_PREFIX} -ef ${CMAKE_CURRENT_SOURCE_DIR}
    RESULT_VARIABLE INSTALL_SOURCE)
if(NOT ${INSTALL_SOURCE} EQUAL 0)
    install(DIRECTORY src DESTINATION .)
    install(DIRECTORY bin DESTINATION . USE_SOURCE_PERMISSIONS)
    install(DIRECTORY include DESTINATION .)
    install(DIRECTORY cmake DESTINATION .)
endif()

#############################
# hip-config
#############################
if(HIP_PLATFORM STREQUAL "hcc")
    install(TARGETS hip_hcc_static hip_hcc host device EXPORT hip-targets DESTINATION ${LIB_INSTALL_DIR})
    install(EXPORT hip-targets DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR} NAMESPACE hip::)
elseif( HIP_PLATFORM STREQUAL "vdi")
#    install(TARGETS hip_on_vdi host device EXPORT hip-targets DESTINATION ${LIB_INSTALL_DIR})
endif()
    include(CMakePackageConfigHelpers)

    configure_package_config_file(
        hip-config.cmake.in
        ${CMAKE_CURRENT_BINARY_DIR}/hip-config.cmake
        INSTALL_DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR}
        PATH_VARS LIB_INSTALL_DIR INCLUDE_INSTALL_DIR BIN_INSTALL_DIR
        )

    write_basic_package_version_file(
        ${CMAKE_CURRENT_BINARY_DIR}/hip-config-version.cmake
        VERSION "${HIP_VERSION_MAJOR}.${HIP_VERSION_MINOR}.${HIP_VERSION_GITDATE}"
        COMPATIBILITY SameMajorVersion
        )
    install(
        FILES
        ${CMAKE_CURRENT_BINARY_DIR}/hip-config.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/hip-config-version.cmake
        DESTINATION
        ${CONFIG_PACKAGE_INSTALL_DIR}
        )

#############################
# Packaging steps
#############################
# Package: hip_base
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/packages/hip-base)
configure_file(packaging/hip-base.txt ${BUILD_DIR}/CMakeLists.txt @ONLY)
configure_file(packaging/hip-base.postinst ${BUILD_DIR}/postinst @ONLY)
configure_file(packaging/hip-base.prerm ${BUILD_DIR}/prerm @ONLY)

add_custom_target(pkg_hip_base COMMAND ${CMAKE_COMMAND} .
    COMMAND rm -rf *.deb *.rpm *.tar.gz
    COMMAND make package
    COMMAND cp *.deb ${PROJECT_BINARY_DIR}
    COMMAND cp *.rpm ${PROJECT_BINARY_DIR}
    COMMAND cp *.tar.gz ${PROJECT_BINARY_DIR}
    WORKING_DIRECTORY ${BUILD_DIR}
    DEPENDS lpl ca)

# Packaging needs to wait for hipify-clang to build if it's enabled...
if (BUILD_HIPIFY_CLANG)
    add_dependencies(pkg_hip_base hipify-clang)
endif()

if(HIP_PLATFORM STREQUAL "hcc")
  message("HCC Package\n")
  # Package: hip_hcc
  set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/packages/hip_hcc)
  configure_file(packaging/hip-hcc.txt ${BUILD_DIR}/CMakeLists.txt @ONLY)
  configure_file(packaging/hip-hcc.postinst ${BUILD_DIR}/postinst @ONLY)
  configure_file(packaging/hip-hcc.prerm ${BUILD_DIR}/prerm @ONLY)
  add_custom_target(pkg_hip_hcc  COMMAND ${CMAKE_COMMAND} .
    COMMAND rm -rf *.deb *.rpm *.tar.gz
    COMMAND make package
    COMMAND cp *.deb ${PROJECT_BINARY_DIR}
    COMMAND cp *.rpm ${PROJECT_BINARY_DIR}
    COMMAND cp *.tar.gz ${PROJECT_BINARY_DIR}
    WORKING_DIRECTORY ${BUILD_DIR}
    DEPENDS hip_hcc hip_hcc_static hiprtc)
else()
  set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/vdi)
  configure_file(packaging/hip-vdi.txt ${BUILD_DIR}/CMakeLists.txt @ONLY)
  configure_file(packaging/hip-vdi.postinst ${BUILD_DIR}/postinst @ONLY)
  configure_file(packaging/hip-vdi.prerm ${BUILD_DIR}/prerm @ONLY)
  add_custom_target(hip_on_vdi COMMAND ${CMAKE_COMMAND} .
    COMMAND rm -rf *.deb *.rpm *.tar.gz
    COMMAND make package
    COMMAND cp *.deb ${PROJECT_BINARY_DIR}
    COMMAND cp *.rpm ${PROJECT_BINARY_DIR}
    COMMAND cp *.tar.gz ${PROJECT_BINARY_DIR}
    WORKING_DIRECTORY ${BUILD_DIR} )
endif()

# Package: hip_nvcc
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/packages/hip-nvcc)
configure_file(packaging/hip-nvcc.txt ${BUILD_DIR}/CMakeLists.txt @ONLY)
add_custom_target(pkg_hip_nvcc COMMAND ${CMAKE_COMMAND} .
    COMMAND rm -rf *.deb *.rpm *.tar.gz
    COMMAND make package
    COMMAND cp *.deb ${PROJECT_BINARY_DIR}
    COMMAND cp *.rpm ${PROJECT_BINARY_DIR}
    COMMAND cp *.tar.gz ${PROJECT_BINARY_DIR}
    WORKING_DIRECTORY ${BUILD_DIR})

# Package: hip_doc
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/packages/hip-doc)
configure_file(packaging/hip-doc.txt ${BUILD_DIR}/CMakeLists.txt @ONLY)
add_custom_target(pkg_hip_doc  COMMAND ${CMAKE_COMMAND} .
    COMMAND rm -rf *.deb *.rpm *.tar.gz
    COMMAND make package
    COMMAND cp *.deb ${PROJECT_BINARY_DIR}
    COMMAND cp *.rpm ${PROJECT_BINARY_DIR}
    COMMAND cp *.tar.gz ${PROJECT_BINARY_DIR}
    WORKING_DIRECTORY ${BUILD_DIR})

# Package: hip_samples
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/packages/hip_samples)
configure_file(packaging/hip-samples.txt ${BUILD_DIR}/CMakeLists.txt @ONLY)
add_custom_target(pkg_hip_samples COMMAND ${CMAKE_COMMAND} .
    COMMAND rm -rf *.deb *.rpm *.tar.gz
    COMMAND make package
    COMMAND cp *.deb ${PROJECT_BINARY_DIR}
    COMMAND cp *.rpm ${PROJECT_BINARY_DIR}
    COMMAND cp *.tar.gz ${PROJECT_BINARY_DIR}
    WORKING_DIRECTORY ${BUILD_DIR})


# Package: all
if(POLICY CMP0037)
    cmake_policy(PUSH)
    cmake_policy(SET CMP0037 OLD)
endif()
file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/fixnames
        CONTENT "pwd; for i in *.deb; do mv \"\$i\" \"\${i/.deb/-amd64.deb}\" ; done
for i in *.rpm ; do mv \$i \${i/.rpm/.x86_64.rpm} ; done
")
if(HIP_PLATFORM STREQUAL "hcc")
    add_custom_target(package
    COMMAND bash ${PROJECT_BINARY_DIR}/fixnames
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    DEPENDS pkg_hip_base pkg_hip_hcc pkg_hip_nvcc pkg_hip_doc pkg_hip_samples)
elseif(HIP_PLATFORM STREQUAL "vdi")
    add_custom_target(package
    COMMAND bash ${PROJECT_BINARY_DIR}/fixnames
    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    DEPENDS pkg_hip_base hip_on_vdi pkg_hip_nvcc pkg_hip_doc pkg_hip_samples)
endif()

if(POLICY CMP0037)
    cmake_policy(POP)
endif()

#############################
# Code analysis
#############################
# Target: cppcheck
find_program(CPPCHECK_EXE cppcheck)
if(CPPCHECK_EXE)
    add_custom_target(cppcheck COMMAND ${CPPCHECK_EXE} --force --quiet --enable=warning,performance,portability,information,missingInclude src include -I /opt/rocm/include/hcc -I /opt/rocm/include --suppress=*:/opt/rocm/include/hcc/hc.hpp
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()

#############################
# Code formatting
#############################
# Target: clangformat
find_program(CLANGFORMAT_EXE clang-format PATHS ${HCC_HOME}/bin)
if(CLANGFORMAT_EXE)
    file(GLOB_RECURSE FORMAT_SOURCE_FILE_LIST *.cpp *.hpp *.h)
    add_custom_target(clangformat COMMAND ${CLANGFORMAT_EXE} -style=file -i ${FORMAT_SOURCE_FILE_LIST}
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
endif()

#############################
# Testing steps
#############################
# Target: test
set(HIP_ROOT_DIR ${CMAKE_INSTALL_PREFIX})
set(HIP_SRC_PATH ${CMAKE_CURRENT_SOURCE_DIR})
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_directory "${HIP_SRC_PATH}/cmake" "${HIP_ROOT_DIR}/cmake" RESULT_VARIABLE RUN_HIT ERROR_QUIET)
if(${RUN_HIT} EQUAL 0)
    execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_directory "${HIP_SRC_PATH}/bin" "${HIP_ROOT_DIR}/bin" RESULT_VARIABLE RUN_HIT ERROR_QUIET)
endif()
if(${RUN_HIT} EQUAL 0)
    set(CMAKE_MODULE_PATH "${HIP_ROOT_DIR}/cmake" ${CMAKE_MODULE_PATH})
    include(${HIP_SRC_PATH}/tests/hit/HIT.cmake)

    # Add tests
    include_directories(${HIP_SRC_PATH}/tests/src)
    hit_add_directory_recursive(${HIP_SRC_PATH}/tests/src "directed_tests")

    # Add unit tests
    include_directories(${HIP_SRC_PATH}/tests/unit)
    hit_add_directory_recursive(${HIP_SRC_PATH}/tests/unit "unit_tests")

    # Add top-level tests to build_tests
    add_custom_target(build_tests DEPENDS directed_tests unit_tests)

    # Add custom target: check
    add_custom_target(check COMMAND "${CMAKE_COMMAND}" --build . --target test DEPENDS build_tests)
else()
    message(STATUS "Testing targets will not be available. To enable them please ensure that the HIP installation directory is writeable. Use -DCMAKE_INSTALL_PREFIX to specify a suitable location")
endif()

#############################
# Code analysis
#############################
# Target: clang
if(HIP_HIPCC_EXECUTABLE)
    add_custom_target(analyze 
        COMMAND ${HIP_HIPCC_EXECUTABLE} -fvisibility=hidden -fvisibility-inlines-hidden --analyze --analyzer-outputtext  -isystem /opt/rocm/include ${HIP_HCC_BUILD_FLAGS} -Wno-unused-command-line-argument -I/opt/rocm/include -c  src/*.cpp -Iinclude/ -I./
    WORKING_DIRECTORY ${HIP_SRC_PATH})
    if(CPPCHECK_EXE)
        add_dependencies(analyze cppcheck)
    endif()
endif()

# vim: ts=4:sw=4:expandtab:smartindent
